package com.magina.antiPro.controller;

import com.magina.antiPro.dto.PayDetailToBabModel;
import lombok.extern.slf4j.Slf4j;
import org.assertj.core.util.Lists;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;

@RestController
@RequestMapping(value = "/payDetail")
@Slf4j
public class PayDetailController {

    private static List<PayDetailToBabModel> payDetail ;
    private static List<PayDetailToBabModel> payDetailCopy ;
    static {
         payDetail = Lists.newArrayList();
        payDetailCopy = Lists.newArrayList();
        for (int i = 0; i < 6; i++) {
            PayDetailToBabModel payDetailToBabModel = new PayDetailToBabModel();
            payDetailToBabModel.setId(i);
            payDetailToBabModel.setProductName("测试" + i);
            payDetailToBabModel.setProductCode("test" + i);
            payDetailToBabModel.setCityId( 1000+ i);
            payDetailToBabModel.setAmount(BigDecimal.valueOf(( 100000+ i)));
            payDetailToBabModel.setMoney(Long.valueOf(i * 999));
            payDetail.add(payDetailToBabModel);
        }
        for (int i = 0; i < 3; i++) {
            PayDetailToBabModel payDetailToBabModel = new PayDetailToBabModel();
            payDetailToBabModel.setId(i);
            payDetailToBabModel.setProductName("测试" + i);
            payDetailToBabModel.setProductCode("test" + i);
            payDetailToBabModel.setCityId( 1000+ i);
            payDetailToBabModel.setAmount(BigDecimal.valueOf(( 888+ i)));
            payDetailToBabModel.setMoney(Long.valueOf(i * 888));
            payDetail.add(payDetailToBabModel);
            payDetailCopy.add(payDetailToBabModel);
        }
    }

    @RequestMapping("/getPayDetail")
    public List<PayDetailToBabModel> getPayDetail() {
        log.info("进入getPayDetail方法!");
        // 分组
        Map<String, List<PayDetailToBabModel>> collect = payDetail.stream().collect(Collectors.groupingBy(PayDetailToBabModel::getCodeAndCityId));

        List<PayDetailToBabModel> results = collect.values().stream().map((List<PayDetailToBabModel> details) ->{
            Long totalMoney = 0L;
            BigDecimal totalAmount = new BigDecimal(0);
            for (PayDetailToBabModel detail : details) {
                totalMoney += detail.getMoney();
                totalAmount = totalAmount.add(detail.getAmount());
            }
            BigDecimal price = null;
            if (totalAmount.equals(new BigDecimal(0))) {
                price = new BigDecimal(totalMoney);
                totalAmount = new BigDecimal(1);
            } else {
                price = new BigDecimal(totalMoney).divide(new BigDecimal(100),6).divide(totalAmount,6);
            }
            PayDetailToBabModel babModel = new PayDetailToBabModel();
            babModel.setMoney(totalMoney);
            babModel.setAmount(totalAmount);
            babModel.setPrice(price);
            babModel.setProductName(details.get(0).getProductName());
            babModel.setProductCode(details.get(0).getProductCode());
            return babModel;
        }).collect(Collectors.toList());
        return  results;
    }
    @RequestMapping("/getPayDetail/sort")
    public List<PayDetailToBabModel> getPayDetail_sort() {
        //正序
        payDetail.sort((a,b) -> a.getId().compareTo(b.getId()));
        payDetail.stream().forEach(p -> System.out.println(p.getId()));
        payDetail.sort((a,b) -> b.getId().compareTo(a.getId()));
        //倒序
        payDetail.stream().forEach(p -> System.out.println(p.getId()));
        Optional maxId = payDetail.stream().max((a, b) -> Integer.compare(a.getId(),b.getId()));
        PayDetailToBabModel model = maxId.isPresent() ? (PayDetailToBabModel) maxId.get() : null;
        Optional minId = payDetail.stream().max((a, b) -> Integer.compare(b.getId(),a.getId()));
        return payDetail;
    }

    @RequestMapping("/getPayDetail/cut")
    public List<PayDetailToBabModel> getPayDetail_cut() {
        payDetail.removeAll(payDetailCopy);
        return payDetail;
    }
    @RequestMapping("/getPayDetail/map")
    public Object getPayDetailToMap() {
        List<String> nameList = payDetail.stream().map(p -> p.getProductName()).collect(Collectors.toList());
        Map<String,PayDetailToBabModel> map = payDetail.stream().collect(Collectors.toMap((key -> key.getAmount().toString()),(value -> value)));
        Map<Object,Object> map1 = payDetail.stream().collect(Collectors.toMap(PayDetailToBabModel::getAmount,PayDetailToBabModel::getProductName));
        return map1;
    }

    @RequestMapping("/getPayDetail/filter")
    public Object getPayDetailTofilter() {
        List<Object> list = payDetail.stream().filter( p -> "测试0".equals(p.getProductName())).map(p -> p.getProductCode()).collect(Collectors.toList());
        Map map = payDetail.stream().filter( p -> "测试0".equals(p.getProductName())).collect(Collectors.toMap((p->p.getAmount()),q->q));

        //map和Collectors.toMap((key -> key.getAmount().toString()),(value -> value)
        String result = payDetail.stream().filter( p -> "测试0".equals(p.getProductName())).map(p -> p.getProductCode()).collect(Collectors.joining());
        //Collectors.joining()的底层是StringBuffer的append方法.value1.apprend(value2)这种
        return result;
    }

    @RequestMapping("/getPayDetail/distanct")
    public Object getPayDetailToDistanct() {
        //此方法只能
        payDetail.stream().distinct();
        System.out.println(payDetail.size());
        payDetail.addAll(payDetailCopy);
        payDetail.stream().distinct();
        System.out.println(payDetail.size());
        List<PayDetailToBabModel> distanctList = payDetail.stream().filter(distinctByKey(PayDetailToBabModel::getId)).collect(Collectors.toList());
        System.out.println(payDetail.size());
        System.out.println(distanctList.size());
        return distanctList;
    }

    /**
     *  通用 根据某个属性去重的方法
     * @param keyExtractor
     * @param <T>
     * @return
     */
    public static <T> Predicate<T> distinctByKey(Function<? super T, Object> keyExtractor) {
        Map<Object, Boolean> seen = new ConcurrentHashMap<>();
        return object -> seen.putIfAbsent(keyExtractor.apply(object), Boolean.TRUE) == null;
    }

    @RequestMapping("/getPayDetail/groupBy")
    public Object getPayDetailToGroup() {
        Map<String, List<PayDetailToBabModel>> groupList = payDetail.stream()
                .collect(Collectors.groupingBy((Function<PayDetailToBabModel, String>) model -> {
                    String key;
                    if (model.getId() <= 2) {
                        key = "less2";
                    } else if (model.getId() <= 4) {
                        key = "less4";
                    } else {
                        key = "more4";
                    }
                    return key;
                }, Collectors.toList()));

        System.out.println(groupList);
        return groupList;
    }

}
